package uk.org.aspellclark.gedcom.model.records;

import java.util.List;
import java.util.StringTokenizer;

import uk.org.aspellclark.gedcom.model.ChangeDate;
import uk.org.aspellclark.gedcom.model.ChildToFamilyLink;
import uk.org.aspellclark.gedcom.model.IndividualEventType;
import uk.org.aspellclark.gedcom.model.LdsIndividualOrdinance;
import uk.org.aspellclark.gedcom.model.SpouseToFamilyLink;
import uk.org.aspellclark.gedcom.model.UserReference;
import uk.org.aspellclark.gedcom.model.structures.AssociationStructure;
import uk.org.aspellclark.gedcom.model.structures.IndividualAttributeStructure;
import uk.org.aspellclark.gedcom.model.structures.IndividualEventStructure;
import uk.org.aspellclark.gedcom.model.structures.MultimediaLink;
import uk.org.aspellclark.gedcom.model.structures.NoteStructure;
import uk.org.aspellclark.gedcom.model.structures.PersonalNameStructure;
import uk.org.aspellclark.gedcom.model.structures.SourceCitation;

/** <pre>INDIVIDUAL_RECORD:=
    n @XREF:INDI@ INDI                        {1:1}
        +1 RESN &lt;RESTRICTION_NOTICE>          {0:1}
        +1 &lt;&lt;PERSONAL_NAME_STRUCTURE>>        {0:M}
        +1 SEX &lt;SEX_VALUE>                    {0:1}
        +1 &lt;&lt;INDIVIDUAL_EVENT_STRUCTURE>>     {0:M}
        +1 &lt;&lt;INDIVIDUAL_ATTRIBUTE_STRUCTURE>> {0:M}
        +1 &lt;&lt;LDS_INDIVIDUAL_ORDINANCE>>       {0:M}
        +1 &lt;&lt;CHILD_TO_FAMILY_LINK>>           {0:M}
        +1 &lt;&lt;SPOUSE_TO_FAMILY_LINK>>          {0:M}
        +1 SUBM @&lt;XREF:SUBM>@                 {0:M}
        +1 &lt;&lt;ASSOCIATION_STRUCTURE>>          {0:M}
        +1 ALIA @&lt;XREF:INDI>@                 {0:M}
        +1 ANCI @&lt;XREF:SUBM>@                 {0:M}
        +1 DESI @&lt;XREF:SUBM>@                 {0:M}
        +1 RFN &lt;PERMANENT_RECORD_FILE_NUMBER> {0:1}
        +1 AFN &lt;ANCESTRAL_FILE_NUMBER>        {0:1}
        +1 REFN &lt;USER_REFERENCE_NUMBER>       {0:M}
            +2 TYPE &lt;USER_REFERENCE_TYPE>     {0:1}
        +1 RIN &lt;AUTOMATED_RECORD_ID>          {0:1}
        +1 &lt;&lt;CHANGE_DATE>>                    {0:1}
        +1 &lt;&lt;NOTE_STRUCTURE>>                 {0:M}
        +1 &lt;&lt;SOURCE_CITATION>>                {0:M}
        +1 &lt;&lt;MULTIMEDIA_LINK>>                {0:M}</pre>
 *<p>
 *The individual record is a compilation of facts, known or discovered, about an individual. Sometimes
these facts are from different sources. This form allows documentation of the source where each of
the facts were discovered.</p><p>
The normal lineage links are shown through the use of pointers from the individual to a family
through either the FAMC tag or the FAMS tag. The FAMC tag provides a pointer to a family where
this person is a child. The FAMS tag provides a pointer to a family where this person is a spouse or
parent. The &lt;&lt;CHILD_TO_FAMILY_LINK>> (see page 31) structure contains a FAMC pointer
which is required to show any child to parent linkage for pedigree navigation. The
&lt;&lt;CHILD_TO_FAMILY_LINK>> structure also indicates whether the pedigree link represents a
birth lineage, an adoption lineage, or a sealing lineage.</p><p>
Linkage between a child and the family they belonged to at the time of an event can also be shown
by a FAMC pointer subordinate to the appropriate event. For example, a FAMC pointer subordinate
to an adoption event indicates a relationship to family by adoption. Biological parents can be shown
by a FAMC pointer subordinate to the birth event(optional).</p><p>
Other associations or relationships are represented by the ASSOciation tag. The person's relation
or association is the person being pointed to. The association or relationship is stated by the value
on the subordinate RELA line. For example:</p>
<pre>
        0 @I1@ INDI
            1 NAME Fred/Jones/
            1 ASSO @I2@
                2 RELA Godfather</pre>
 */
public class IndividualRecord extends GedcomRecord {

	public boolean noIndividualsInDatabase = false;
	public String resn;
	public List<PersonalNameStructure> names;
	public String sex;
	public List<IndividualEventStructure> indEvent;
	public List<IndividualAttributeStructure> indAttr;
	public List<LdsIndividualOrdinance> ldsIndOrd;
	public List<ChildToFamilyLink> childLink;
	public List<SpouseToFamilyLink> spouseLink;
	public List<String> submXRef;
	public List<AssociationStructure> associationStructure;
	public List<String> aliasXRef;
	public List<String> anciXRef;
	public List<String> desiXRef;
	public String rfn;
	public String afn;
	public List<UserReference> refn;
	public String rin;
	public ChangeDate changeDate;
	public List<NoteStructure> note;
	public List<SourceCitation> sourceCitation;
	public List<MultimediaLink> multimediaLink;

	public IndividualRecord(String idFromString) {
		this.xref = idFromString;
	}

	public CharSequence getBirthPlace() {
		String dobStr = "unknown";
		if (this.indEvent != null) {
			for (IndividualEventStructure ie : this.indEvent) {
				if (ie.type != null) {
					if (ie.type.tag.equalsIgnoreCase(IndividualEventType.BIRTH.tag)) {
						if (ie.detail.eventDetail.place != null) {
							dobStr = ie.detail.eventDetail.place.name;
							break;
						}
					}
				}
			}
		}
		return dobStr;
	}

	/**
	 * return the date of birth as a string;
	 * @return
	 */
	public String getDOB() {
		String dobStr = "n/a";
		if (this.indEvent != null) {
			for (IndividualEventStructure ie : this.indEvent) {
				if (ie.type != null) {
					if (ie.type.tag.equalsIgnoreCase(IndividualEventType.BIRTH.tag)) {
						if (ie.detail.date != null) {
							dobStr = ie.detail.date;
						}
					}
				}
			}
		}
		return dobStr;
	}

	/**
	 * return the date of death as a string;
	 * @return
	 */
	public String getDOD() {
		String dobStr = "n/a";
		if (this.indEvent != null) {
			for (IndividualEventStructure ie : this.indEvent) {
				if (ie.type != null) {
					if (ie.type.tag.equalsIgnoreCase(IndividualEventType.DEATH.tag)) {
						if (ie.detail.date != null) {
							dobStr = ie.detail.date;
						}
					}
				}
			}
		}
		return dobStr;
	}

	public String getName() {
		String meStr = "";
		PersonalNameStructure psn = null;
		if (this.names.size() > 0) {
			psn = this.names.get(0);
		}
		if (psn != null) {
			if (psn.name != null) {
				final StringTokenizer tok = new StringTokenizer(psn.name);
				// final String[] tokenList = new String[tok.countTokens()];
				// int x = 0;
				while (tok.hasMoreTokens()) {
					meStr += " " + tok.nextToken();
				}
			} else {
				meStr += (psn.pieces.given != null ? psn.pieces.given : "");
				meStr += " " + (psn.pieces.surname != null ? psn.pieces.surname : "");
			}
		}
		return meStr.trim();
	}

	public String getNameFirst() {
		String meStr = this.getName();
		if (meStr.length() > 0) {
			final StringTokenizer tok = new StringTokenizer(meStr, "/");
			meStr = tok.nextToken();
		}
		return meStr.trim();
	}

	public String getNameLast() {
		String meStr = this.getName();
		String lastname = "";
		if (meStr.length() > 0) {
			final StringTokenizer tok = new StringTokenizer(meStr, "/");
			if (tok.countTokens() > 1) {
				meStr = tok.nextToken();
				lastname = tok.nextToken();
			}
		}
		return lastname.trim();
	}
}
